﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace MemoryLeakViewerLib
{
    public static class VldOutputParser
    {
        public static List<MemoryLeak> Parse(string AbsoluteFilePath)
        {
            List<MemoryLeak> memoryLeaks = new List<MemoryLeak>();

            if (!File.Exists(AbsoluteFilePath))
            {
                Debug.Assert(false);
                return memoryLeaks;
            }

            string[] lines = System.IO.File.ReadAllLines(AbsoluteFilePath);

            List<string> callStackList = new List<string>();
            List<string> dataList = new List<string>();
            string headerText = "";
            int size = 0;
            int count = 0;


            bool HeaderInfo = true;
            bool gettingCallStack = false;
            bool gettingData = false;
            foreach (string line in lines)
            {
                Regex LeadingWhiteSpace = new Regex("^\\s*");
                Regex TrailingWhiteSpace = new Regex("\\s*$");

                Regex Start = new Regex("---------- Block [0-9]* at [\\S]*: ([0-9]*) bytes ----------");
                Regex Info = new Regex("^Leak Hash: [\\S]* Count: ([0-9]*)");
                Regex CallStackBegin = new Regex("^  Call Stack:$");
                Regex DataBegin = new Regex("^  Data:$");
                if (Start.Match(line).Success)
                {
                    // If this is not our first time
                    if (!HeaderInfo)
                    {
                        memoryLeaks.Add(new MemoryLeak(count, size, callStackList, dataList));
                    }
                    HeaderInfo = false;
                    gettingCallStack = false;
                    gettingData = false;

                    callStackList.Clear();
                    dataList.Clear();

                    Match m = Start.Match(line);
                    //string header = m.Groups[0].Value;
                    size = Convert.ToInt32(m.Groups[1].Value);
                }
                else if (Info.Match(line).Success)
                {
                    Match m = Info.Match(line);
                    count = Convert.ToInt32(m.Groups[1].Value);
                }
                else if (CallStackBegin.Match(line).Success)
                {
                    gettingCallStack = true;
                }
                else if (DataBegin.Match(line).Success)
                {
                    gettingData = true;
                    gettingCallStack = false;
                }
                else if (gettingCallStack)
                {
                    string lineNoSpaces = LeadingWhiteSpace.Replace(line, "");
                    callStackList.Add(lineNoSpaces);
                }
                else if (gettingData)
                {
                    string lineNoSpaces = LeadingWhiteSpace.Replace(line, "");
                    if (lineNoSpaces != "")
                    {
                        dataList.Add(lineNoSpaces);
                    }
                }
                else if (HeaderInfo)
                {
                    headerText += line;
                }

                // Use a tab to indent each line of the file.
                //Console.WriteLine("\t" + line);
            }

            return memoryLeaks;
        }
    }
}
